export default class {
    el = null;
    _isStart = false;
    _startStamp = -1;
    _lastStamp = -1;
    _interStamp = -1;
    _animationId = -1;
    _frames = [];

    constructor(el) {
        if (typeof el == 'string') {
            this.el = document.querySelector(el);
        } else if (el instanceof HTMLElement) {
            this.el = el;
        }
    }

    start() {
        if (!this._isStart) {
            this._isStart = true;
            this._startStamp = -1;
            this._lastStamp = -1;
            this._interStamp = -1;
            this._animationId = requestAnimationFrame((stamp) => {
                this.step(stamp);
            });
        }
        return this;
    }

    step(stamp) {
        if (!this._isStart) {
            return this;
        }
        if (this._startStamp == -1) {
            this._startStamp = stamp
        }
        if (this._lastStamp == -1) {
            this._lastStamp = stamp;
        }
        this._interStamp = stamp - this._lastStamp;
        this._lastStamp = stamp;
        const grapStamp = stamp - this._startStamp;
        this._frames.forEach(fn => fn.call(this, grapStamp, this._interStamp, this));
        requestAnimationFrame(stamp => this.step(stamp));
        return this;
    }

    stop() {
        if (this._isStart) {
            cancelAnimationFrame(this._animationId);
            this._isStart = false;
        }
        return this;
    }
    cancel() {
        if (this._isStart) {
            cancelAnimationFrame(this._animationId);
            this._isStart = false;
            this._startStamp = -1;
            this._lastStamp = -1;
            this._interStamp = -1;
            this._frames = [];
        }
        return this;
    }

    addFrame(fn) {
        if (typeof fn == 'function') {
            this._frames.push(fn);
        }
        return this;
    }

}